﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ParallelEx
{
    public class ParallelHelper
    {
        /// <summary>
        /// ForEach
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="datas">数据源</param>
        /// <param name="batchSize">分批大小</param>
        /// <param name="threadCount">线程大小</param>
        /// <param name="action">分批索引,T,分批字典</param>
        public static ParallelLoopResult ForEach<T>(IEnumerable<T> datas, int batchSize, int threadCount, Action<int, IEnumerable<T>, Dictionary<int, IEnumerable<T>>> action)
        {
            var batchs = new Dictionary<int, IEnumerable<T>>();
            CreatePage(datas, batchSize, batchs);

            return Parallel.ForEach(batchs, CreateParallelOptions(threadCount), lst =>
            {
                action.Invoke(lst.Key, lst.Value, batchs);
            });
        }


        /// <summary>
        /// ForEach
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <param name="datas">数据源</param>
        /// <param name="batchSize">分批大小</param>
        /// <param name="threadCount">线程大小</param>
        /// <param name="action">分批索引,T</param>
        public static ParallelLoopResult ForEach<T>(IEnumerable<T> datas, int batchSize, int threadCount, Action<int, IEnumerable<T>> action)
        {
            var batchs = new Dictionary<int, IEnumerable<T>>();
            CreatePage(datas, batchSize, batchs);

            return Parallel.ForEach(batchs, CreateParallelOptions(threadCount), lst =>
            {
                action.Invoke(lst.Key, lst.Value);
            });
        }

        private static void CreatePage<T>(IEnumerable<T> datas, int batchSize, Dictionary<int, IEnumerable<T>> batchs)
        {
            int idx = 0;
            PageHelper.PageEach<T>(datas, batchSize, list =>
            {
                idx++;

                batchs.Add(idx, list);
            });
        }

        private static ParallelOptions CreateParallelOptions(int threadCount)
        {
            return new ParallelOptions
            {
                MaxDegreeOfParallelism = threadCount
            };
        }
    }
}
